package pers.mor.tomcat.servlet;

import pers.mor.tomcat.catalina.Context;
import pers.mor.tomcat.classloader.WebappClassLoader;
import pers.mor.tomcat.http.Constant;
import pers.mor.tomcat.http.Request;
import pers.mor.tomcat.http.Response;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class InvokeServlet extends HttpServlet {

    private InvokeServlet() {

    }

    private static InvokeServlet servlet;

    public static InvokeServlet instance(){
        if (servlet == null) {
            servlet = new InvokeServlet();
        }
        return servlet;
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Request request = (Request)req;
        Response response = (Response)resp;

        try {
            Context context = request.getContext();

            String servletClassName = context.getServletClassName(request.getUri());

            WebappClassLoader webappClassLoader = context.getWebappClassLoader();
            Class aClass = webappClassLoader.loadClass(servletClassName);
            HttpServlet servlet = context.getServlet(aClass);

            Method[] methods = aClass.getMethods();
            for (Method method : methods) {
                if (method.getName().equals("service")) {
                    method.invoke(servlet, request, response);
                }
            }

            if (request.isForwarded() == true) {
                return;
            }

            if (request.isInclude() == true) {
                request.setInclude(false);
                return;
            }

            if (response.getRedirectPath() != null) {
                response.setStatus(Constant.CODE_302);
            } else {
                response.setStatus(Constant.CODE_200);
            }

        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        }
    }

}
